#include "lua_entityhooks.h"

std::map< int, CEntity *> m_vMappedEntities;

CEntity * GetEntity( int id )
{
	
	CEntity * e = NULL;
	/*
	try
	{
		
		e = m_vMappedEntities.at( id );
		
	} catch( std::exception & err )*/
	{
		
		e = g_pGameInterface->GetEntityFactory()->GetStateVec()->GetEntity( id );

		if( e )
		{

			m_vMappedEntities[id] = e;
			
		}
		
	}
	
	return e;
	
}

void CGameInterface::CreateLuaEntityHooks()
{
	
	RegisterNameSpace( m_pLuaState, "EntDataTable" );
	RegisterNameSpace( m_pLuaState, "EntCallBacks" );
	
	RegisterNameSpace( m_pLuaState, "Entity" );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "SetPos", LUAENTITY_SetPos );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "GetPos", LUAENTITY_GetPos );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "GenerateHit", LUAENTITY_GenHit );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "SetCurrentSprite", LUAENTITY_SetCurrentSprite );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "EngineGetTable", LUAENTITY_GetTable );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "GetCenter", LUAENTITY_GetCenterPos );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "GetSize", LUAENTITY_GetSize );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "SetAnimating", LUAENTITY_SetAnimating );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "IsValid", LUAENTITY_IsValid );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "SetConstantVelocity", LUAENTITY_SetConstantVel );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "Flip", LUAENTITY_Flip );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "IsFlipped", LUAENTITY_IsFlipped );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "New", LUAENTITY_New );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "AddSprite", LUAENTITY_AddSprite );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "AddShadow", LUAENTITY_AddShadow );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "SetHasShadow", LUAENTITY_SetHasShadow );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "AddCollisionBox", LUAENTITY_AddCollisionBox );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "Scale", LUAENTITY_Scale );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "GiveNPCLogic", LUAENTITY_GiveNPCLogic );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "RegisterCallback", LUAENTITY_RegisterCallback );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "SetDoLogic", LUAENTITY_SetDoLogic );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "SetCurrentSpriteBind", LUAENTITY_SetCurrentSpriteBind );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "Remove", LUAENTITY_Remove );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "BindSprite", LUAENTITY_BindSprite );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "IdleAnim", LUAENTITY_IdleAnim );
		RegisterNameSpaceFunction( m_pLuaState, "Entity", "RunAnim", LUAENTITY_RunAnim );
		
}

int LUAENTITY_SetDoLogic( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );
	bool b = lua_toboolean( s, 2 );
	
	CEntity * e = GetEntity( id );

	if( e )
	{
		
		e->SetEntityDoLogic( b );
		
	}
	
	return 0;
	
}

int LUAENTITY_RegisterCallback( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );
	std::string funcname = lua_tostring( s, 2 );
	int ref = luaL_ref( s, LUA_REGISTRYINDEX );
	
	lua_getglobal( s, "EntCallBacks" );
	lua_pushnumber( s, id );
	
	lua_gettable( s, -2 );
	
	if( LuaNil( s ) )
	{
		
		lua_pop( s, 1 );
		
		lua_pushnumber( s, id );
		lua_newtable( s );
		lua_settable( s, -3 );
		
		lua_pushnumber( s, id );
		lua_gettable( s, -2 );
		
	} 
	
	lua_rawgeti( s, LUA_REGISTRYINDEX, ref );
	lua_setfield( s, -2, funcname.c_str() );
	
	lua_pop( s, 2 );
	
	return 0;
	 
}

int LUAENTITY_GiveNPCLogic( lua_State * s )
{

	int id = LuaStringKeyIntValue( s, 1, "id" );

	bool enemy = false;
	
	if( lua_gettop( s ) >= 2 )
	{
		
		enemy = lua_toboolean( s, 2 );
		
	}
	
	CEntity * e = GetEntity( id );

	if( e )
	{
		
		CNPCLogic * npc = new CNPCLogic;
		
		npc->SetEntity( e );
		npc->SetIsEnemy( enemy );
		
		e->SetEntityLogic( npc );
		
	}
	
	return 0;
	
}

int LUAENTITY_Scale( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );

	double xmul = lua_tonumber( s, 2 );
	double ymul = lua_tonumber( s, 3 );
	
	CEntity * e = GetEntity( id );

	if( e )
	{
		
		e->Scale( xmul, ymul );
		
	}
	
	return 0;
	
}

int LUAENTITY_IsFlipped( lua_State * s )
{

	int id = LuaStringKeyIntValue( s, 1, "id" );

	CEntity * e = GetEntity( id );

	if( e )
	{
		
		lua_pushboolean( s, e->IsFlipped() );
		
	}
	
	return 1;
	
}

int LUAENTITY_BindSprite( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );

	CEntity * e = GetEntity( id );
	
	if( e )
	{
		
		bool bCur = false;
		
		std::string dir = lua_tostring( s, 2 );
		
		int bind = lua_tonumber( s, 3 );
		
		if( lua_gettop( s ) == 4 )
			bCur = lua_toboolean( s, 4 );
		
		CMaterial * mat = g_pGameInterface->Graphics()->Find( dir );
		
		if( mat )
			e->BindSprite( mat, bind, bCur );
			
	}
	
	return 0;
	
}

int LUAENTITY_AddSprite( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );

	CEntity * e = GetEntity( id );
	
	if( e )
	{
		
		bool bCur = false;
		
		std::string dir = lua_tostring( s, 2 );
		
		if( lua_gettop( s ) == 3 )
			bCur = lua_toboolean( s, 3 );
		
		CMaterial * mat = g_pGameInterface->Graphics()->Find( dir );
		
		if( mat )
			e->AddSprite( mat, bCur );
			
	}
	
	return 0;
	
}

int LUAENTITY_AddCollisionBox( lua_State * s )
{

	int id = LuaStringKeyIntValue( s, 1, "id" );

	int frame = lua_tonumber( s, 2 );
	double xmul = lua_tonumber( s, 3 );
	double ymul = lua_tonumber( s, 4 );
	
	bool bShift = false;
	
	if( lua_gettop( s ) >= 5 )
		bShift = lua_toboolean( s, 5 );
	
	CEntity * e = GetEntity( id );
	
	if( e )
	{
		
		e->FitCollisionBoxToSprite( frame, xmul, ymul );
		
		if( bShift )
			e->ShiftCollisionBoxToBottom();
		
	}
	
	return 0;
	
}

int LUAENTITY_SetHasShadow( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );
	bool has_shadow = lua_toboolean( s, 2 );
	
	CEntity * e = GetEntity( id );
	
	if( e )
	{
		
		e->SetHasShadow( has_shadow );
		
	}
	
	return 0;
	
}

int LUAENTITY_AddShadow( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );

	double xmul = lua_tonumber( s, 2 );
	double ymul = lua_tonumber( s, 3 );
	int xoffset = lua_tonumber( s, 4 );
	int yoffset = lua_tonumber( s, 5 );
	
	CEntity * e = GetEntity( id );
	
	if( e )
	{
		
		e->SetHasShadow( true );
		e->SetShadowScale( xmul, ymul );
		e->SetShadowOffset( xoffset, yoffset );
		
	}
	
	return 0;
	
}

int LUAENTITY_Remove( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );
	
	int n = -1;
	
	if( lua_gettop( s ) >= 2 )
		n = lua_tonumber( s, 2 );
	
	g_pGameInterface->GetEntityFactory()->GetStateVec( n )->RemoveEntity( id );
	
}

int LUAENTITY_New( lua_State * s )
{
	
	CEntity * e = g_pGameInterface->CreateEntity();
	
	lua_newtable( s );
	
	lua_pushnumber( s, e->GetUniqueID() );
	lua_setfield( s, -2, "id" );
	
	lua_newtable( s );
	
	lua_getglobal( s, "Entity" );
	lua_setfield( s, -2, "__index" );
	
	lua_setmetatable( s, -2 );
	
	return 1;
	
}

int LUAENTITY_Flip( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );

	CEntity * e = GetEntity( id );

	if( e )
	{
		
		e->Flip();
		
	}
	
	return 0;
	
}

int LUAENTITY_GetSize( lua_State * s )
{

	
	int id = LuaStringKeyIntValue( s, 1, "id" );

	CEntity * e = GetEntity( id );

	if( e )
	{
		
		Vector2D v = e->GetSize();
	
		lua_newtable( s );
		
		lua_pushnumber( s, v.x );
		lua_setfield( s, -2, "w" );
		
		lua_pushnumber( s, v.y );
		lua_setfield( s, -2, "h" );
		return 1;
		
	}
		
	return 0;
}

int LUAENTITY_GetCenterPos( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );

	CEntity * e = GetEntity( id );

	if( e )
	{
		
		Vector2D v = e->GetCenter();
	
		lua_newtable( s );
		
		lua_pushnumber( s, v.x );
		lua_setfield( s, -2, "x" );
		
		lua_pushnumber( s, v.y );
		lua_setfield( s, -2, "y" );
		return 1;
		
	}
		
	return 0;
	
}

int LUAENTITY_SetConstantVel( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );
	
	float x = lua_tonumber( s, 2 );
	float y = lua_tonumber( s, 3 );
	
	CEntity * e = GetEntity( id );
	
	if( e )
	{
		
		e->SetConstantVel( x, y );
		
	}
	
	return 0;
	
}


int LUAENTITY_GenHit( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );
	int victimid = LuaStringKeyIntValue( s, 2, "id" );
	int count = -1;
	
	if( lua_gettop( s ) > 2 )
		count = lua_tonumber( s, 3 );	
	
	CEntity * e = GetEntity( id );

	if( e )
		g_pGameInterface->BattleSystem()->GenerateHit( id, victimid, count );
	
	return 0;
	
}


int LUAENTITY_RunAnim( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );

	CEntity * e = GetEntity( id );
	
	if( e )
		e->RunAnim();
	
	return 0;
		
}

int LUAENTITY_IdleAnim( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );

	CEntity * e = GetEntity( id );

	if( e )
		e->IdleAnim();
	
	return 0;
		
}

int LUAENTITY_GetTable( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );
	
	LuaGetEntityTable( s, id );
	
	lua_remove( s, -2 );
	
	return 1;
	
}

int LUAENTITY_GetPos( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );

	CEntity * e = GetEntity( id );

	if( e )
	{
		
		Vector2D v = e->GetPos();
	
		lua_newtable( s );
		
		lua_pushnumber( s, v.x );
		lua_setfield( s, -2, "x" );
		
		lua_pushnumber( s, v.y );
		lua_setfield( s, -2, "y" );
		return 1;
		
	}
		
	return 0;
	
}

int LUAENTITY_SetCurrentSpriteBind( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );
	int bind = lua_tonumber( s, 2 );

	CEntity * e = GetEntity( id );

	if( e )
		e->SetCurrentSpriteBind( bind );
	
	return 0;
	
}

int LUAENTITY_SetCurrentSprite( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );
	int sprite = lua_tonumber( s, 2 );

	CEntity * e = GetEntity( id );

	if( e )
		e->SetCurrentSprite( sprite );
	
	return 0;
	
}

int LUAENTITY_SetAnimating( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );
	bool animating = lua_toboolean( s, 2 );

	CEntity * e = GetEntity( id );

	if( e )
		e->SetAnimating( animating );
	
	return 0;
	
}

int LUAENTITY_SetPos( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );
	float x = lua_tonumber( s, 2 );
	float y = lua_tonumber( s, 3 );

	CEntity * e = GetEntity( id );

	if( e )
		e->SetPos( x, y );
	
	return 0;
	
}

int LUAENTITY_IsValid( lua_State * s )
{
	
	int id = LuaStringKeyIntValue( s, 1, "id" );

	CEntity * e = GetEntity( id );
	
	lua_pushboolean( s, !( e == NULL ) );
	
	return 1;
	
}